package com.Webserver.http;

import com.sun.javafx.collections.MappingChange;

import java.io.*;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HttpResponse {
    private int statusCode = 200;
    private String statusReason = "OK";

    private Map<String, String> headers = new HashMap<>();

    private File entity;
    private Socket socket;

    private byte[] contentData;
    private ByteArrayOutputStream baos;
    private PrintWriter printWriter;

    public HttpResponse(Socket socket) {
        this.socket = socket;
    }

    public void flush() throws IOException {
        sendBefore();
        sendStatusLine();
        sendHeaders();
        sendContent();
    }

    public void sendBefore() {
        if (baos != null) {
            contentData = baos.toByteArray();
            if (contentData != null) {
                this.putHeader("Content-Length", contentData.length + "");
            }
        }
    }

    private void sendStatusLine() throws IOException {
        String line = "HTTP/1.1" + " " + statusCode + " " + statusReason;
        println(line);
    }

    private void sendHeaders() throws IOException {

        Set<Map.Entry<String, String>> entrySet = headers.entrySet();
        for (Map.Entry<String, String> e : entrySet) {
            String name = e.getKey();
            String value = e.getValue();
            String line = name + ": " + value;
            println(line);
        }
        println("");
    }

    private void sendContent() throws IOException {
        if (contentData != null) {
            OutputStream out = socket.getOutputStream();
            out.write(contentData);
        } else if (entity != null) {
            try (
                    FileInputStream fis = new FileInputStream(entity);
            ) {
                OutputStream out = socket.getOutputStream();
                byte[] data = new byte[1024 * 10];
                int num;
                while ((num = fis.read(data)) != -1) {
                    out.write(data, 0, num);
                }
            }
        }
    }

    private void println(String line) throws IOException {
        OutputStream out = socket.getOutputStream();
        byte[] data = line.getBytes("ISO8859-1");
        out.write(data);
        out.write(13);
        out.write(10);
    }

    public int getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }

    public String getStatusReason() {
        return statusReason;
    }

    public void setStatusReason(String statusReason) {
        this.statusReason = statusReason;
    }

    public File getEntity() {
        return entity;
    }

    public void setEntity(File entity) {
        this.entity = entity;
        String len = entity.getName();
        String ext = len.substring(len.lastIndexOf(".") + 1);
        String type = HttpContext.getMimeMapping(ext);
        System.out.println(ext + "的mime type:" + type);

        putHeader("Content-Type", type);
        putHeader("Content-Length", entity.length() + "");
    }

    public void putHeader(String name, String value) {
        this.headers.put(name, value);
    }

    public PrintWriter getWriter() {
        if (baos != null) {
            baos = new ByteArrayOutputStream();
            printWriter = new PrintWriter(
                    new BufferedWriter(
                            new OutputStreamWriter(
                                    baos
                            )
                    ), true
            );
        }
        return printWriter;
    }

    public void setContentType(String mime){
        this.putHeader("Content-Type", mime);
    }
}
